#pragma once

#include <string>
#include <vector>
#include <map>
#include <memory>

#include "../CLink_Export.h"

namespace CLink 
{
namespace Db 
{

/**
 * @brief 查询类型枚举
 * 
 * 定义了SQL查询的基本类型
 */
enum class QueryType {
    SELECT,    ///< 查询数据
    INSERT,    ///< 插入数据
    UPDATE,    ///< 更新数据
    DELETED    ///< 删除数据
};

/**
 * @brief 连接类型枚举
 * 
 * 定义了SQL JOIN操作的类型
 */
enum class JoinType {
    INNER,    ///< 内连接
    LEFT,     ///< 左连接
    RIGHT     ///< 右连接
};

/**
 * @brief WHERE条件类型枚举
 * 
 * 定义了WHERE条件的连接方式
 */
enum class WhereType {
    WHERE,    ///< 基本WHERE条件
    AND,      ///< AND连接条件
    OR        ///< OR连接条件
};

/**
 * @brief 连接子句结构体
 * 
 * 用于存储JOIN操作的相关信息
 */
struct JoinClause {
    JoinType type;           ///< 连接类型
    std::string table;       ///< 要连接的表名
    std::string condition;   ///< 连接条件
};

/**
 * @brief 操作符类型枚举
 * 
 * 定义了SQL条件表达式中可用的操作符
 */
enum class OperatorType {
    EQUAL,         ///< 等于
    NOT_EQUAL,     ///< 不等于
    LESS,          ///< 小于
    LESS_EQUAL,    ///< 小于等于
    GREATER,       ///< 大于
    GREATER_EQUAL, ///< 大于等于
    LIKE,          ///< LIKE模糊匹配
    NOT_LIKE,      ///< NOT LIKE模糊匹配
    IS_NULL,       ///< IS NULL
    IS_NOT_NULL,   ///< IS NOT NULL
    IS_IN,         ///< IN集合
    NOT_IN,        ///< NOT IN集合
    BETWEEN,       ///< BETWEEN范围
    NOT_BETWEEN    ///< NOT BETWEEN范围
};

/**
 * @brief WHERE条件子句结构体
 * 
 * 用于存储WHERE条件的相关信息
 */
struct CLINK_CLASS WhereClause {
    WhereType type;      ///< 条件类型
    std::string column;  ///< 列名
    std::string op;      ///< 操作符
    std::string value;   ///< 比较值
    bool raw;            ///< 是否为原始SQL表达式
};

/**
 * @brief 排序子句结构体
 * 
 * 用于存储ORDER BY子句的相关信息
 */
struct CLINK_CLASS OrderClause {
    std::string column;  ///< 排序列名
    bool ascending;      ///< 是否升序排列
};

CLINK_CLASS std::string operatorToString(CLink::Db::OperatorType op);

/**
 * @brief SQL查询构建器类
 * 
 * 提供流式API来构建SQL查询，支持SELECT、INSERT、UPDATE和DELETE操作
 */
class CLINK_CLASS QueryBuilder {
public:
    /**
     * @brief 构造函数
     * 
     * 创建一个新的查询构建器实例
     */
    QueryBuilder();
    
    /**
     * @brief 析构函数
     */
    ~QueryBuilder() = default;

    /**
     * @brief 设置要查询的列
     * @param columns 列名数组
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& select(const std::vector<std::string>& columns);
    
    /**
     * @brief 设置要查询的单个列
     * @param column 列名
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& select(const std::string& column);
    
    /**
     * @brief 设置原始SELECT表达式
     * @param expression 原始SQL表达式
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& selectRaw(const std::string& expression);
    
    /**
     * @brief 设置DISTINCT查询
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& distinct();
    
    /**
     * @brief 设置要查询的表
     * @param table 表名
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& from(const std::string& table);

    /**
     * @brief 添加JOIN子句
     * @param table 要连接的表名
     * @param first 第一个连接列
     * @param op 操作符类型
     * @param second 第二个连接列
     * @param type 连接类型
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& join(const std::string& table, 
                     const std::string& first, 
                     OperatorType op,
                     const std::string& second, 
                     JoinType type = JoinType::INNER);
    
    /**
     * @brief 添加LEFT JOIN子句
     * @param table 要连接的表名
     * @param first 第一个连接列
     * @param op 操作符类型
     * @param second 第二个连接列
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& leftJoin(const std::string& table, 
                         const std::string& first, 
                         OperatorType op,
                         const std::string& second);
    
    /**
     * @brief 添加RIGHT JOIN子句
     * @param table 要连接的表名
     * @param first 第一个连接列
     * @param op 操作符类型
     * @param second 第二个连接列
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& rightJoin(const std::string& table, 
                          const std::string& first, 
                          OperatorType op,
                          const std::string& second);
    
    /**
     * @brief 添加INNER JOIN子句
     * @param table 要连接的表名
     * @param first 第一个连接列
     * @param op 操作符类型
     * @param second 第二个连接列
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& innerJoin(const std::string& table, 
                          const std::string& first, 
                          OperatorType op,
                          const std::string& second);

    /**
     * @brief 添加WHERE条件
     * @param column 列名
     * @param op 操作符类型
     * @param value 比较值
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& where(const std::string& column, 
                        OperatorType op,
                        const std::string& value);
    
    /**
     * @brief 添加WHERE等于条件
     * @param column 列名
     * @param value 比较值
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& where(const std::string& column, 
                      const std::string& value);
    
    /**
     * @brief 添加原始WHERE条件
     * @param raw 原始SQL WHERE表达式
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& whereRaw(const std::string& raw);
    
    /**
     * @brief 添加OR WHERE条件
     * @param column 列名
     * @param op 操作符类型
     * @param value 比较值
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& orWhere(const std::string& column, 
                          OperatorType op,
                        const std::string& value);
    
    /**
     * @brief 添加OR WHERE等于条件
     * @param column 列名
     * @param value 比较值
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& orWhere(const std::string& column, 
                        const std::string& value);
    
    /**
     * @brief 添加原始OR WHERE条件
     * @param raw 原始SQL OR WHERE表达式
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& orWhereRaw(const std::string& raw);
    
    /**
     * @brief 添加WHERE IN条件
     * @param column 列名
     * @param values 值列表
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& whereIn(const std::string& column, 
                        const std::vector<std::string>& values);
    
    /**
     * @brief 添加WHERE NOT IN条件
     * @param column 列名
     * @param values 值列表
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& whereNotIn(const std::string& column, 
                           const std::vector<std::string>& values);
    
    /**
     * @brief 添加WHERE IS NULL条件
     * @param column 列名
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& whereNull(const std::string& column);
    
    /**
     * @brief 添加WHERE IS NOT NULL条件
     * @param column 列名
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& whereNotNull(const std::string& column);
    
    /**
     * @brief 添加WHERE BETWEEN条件
     * @param column 列名
     * @param min 最小值
     * @param max 最大值
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& whereBetween(const std::string& column, 
                             const std::string& min, 
                             const std::string& max);
    
    /**
     * @brief 添加WHERE NOT BETWEEN条件
     * @param column 列名
     * @param min 最小值
     * @param max 最大值
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& whereNotBetween(const std::string& column, 
                                const std::string& min, 
                                const std::string& max);

    /**
     * @brief 添加GROUP BY子句
     * @param column 分组列名
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& groupBy(const std::string& column);
    
    /**
     * @brief 添加多列GROUP BY子句
     * @param columns 分组列名列表
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& groupBy(const std::vector<std::string>& columns);
    
    /**
     * @brief 添加HAVING子句
     * @param column 列名
     * @param op 操作符类型
     * @param value 比较值
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& having(const std::string& column, 
                        OperatorType op,
                        const std::string& value);
    
    /**
     * @brief 添加OR HAVING子句
     * @param column 列名
     * @param op 操作符类型
     * @param value 比较值
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& orHaving(const std::string& column, 
                           OperatorType op,
                           const std::string& value);

    /**
     * @brief 添加ORDER BY子句
     * @param column 排序列名
     * @param ascending 是否升序排列，默认为true
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& orderBy(const std::string& column, bool ascending = true);
    
    /**
     * @brief 添加降序ORDER BY子句
     * @param column 排序列名
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& orderByDesc(const std::string& column);

    /**
     * @brief 设置LIMIT子句
     * @param limit 限制返回的记录数
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& limit(int limit);
    
    /**
     * @brief 设置OFFSET子句
     * @param offset 跳过的记录数
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& offset(int offset);
    
    /**
     * @brief 设置分页
     * @param page 页码（从1开始）
     * @param perPage 每页记录数，默认为10
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& page(int page, int perPage = 10);

    /**
     * @brief 设置INSERT操作的数据
     * @param data 键值对形式的数据，键为列名，值为要插入的值
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& insert(const std::map<std::string, std::string>& data);
    
    /**
     * @brief 设置批量INSERT操作的数据
     * @param data 包含多条记录的数据，每条记录为键值对形式，键为列名，值为要插入的值
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& insert(const std::vector<std::map<std::string, std::string>>& data);

    /**
     * @brief 设置UPDATE操作的数据
     * @param data 键值对形式的数据，键为列名，值为要更新的值
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& update(const std::map<std::string, std::string>& data);

    /**
     * @brief 设置DELETE操作
     * @return 查询构建器引用，用于链式调用
     */
    QueryBuilder& del();

    /**
     * @brief 构建SQL语句
     * @return 构建好的SQL查询字符串
     */
    std::string build() const;

    /**
     * @brief 重置查询构建器
     * 
     * 清除所有已设置的查询条件和参数，使构建器恢复到初始状态
     */
    void reset();

private:
    /**
     * @brief 构建SELECT子句
     * @param sql SQL语句输出流
     */
    void buildSelect(std::ostringstream& sql) const;
    
    /**
     * @brief 构建INSERT子句
     * @param sql SQL语句输出流
     */
    void buildInsert(std::ostringstream& sql) const;
    
    /**
     * @brief 构建UPDATE子句
     * @param sql SQL语句输出流
     */
    void buildUpdate(std::ostringstream& sql) const;
    
    /**
     * @brief 构建DELETE子句
     * @param sql SQL语句输出流
     */
    void buildDelete(std::ostringstream& sql) const;
    
    /**
     * @brief 构建JOIN子句
     * @param sql SQL语句输出流
     */
    void buildJoins(std::ostringstream& sql) const;
    
    /**
     * @brief 构建WHERE子句
     * @param sql SQL语句输出流
     */
    void buildWheres(std::ostringstream& sql) const;
    
    /**
     * @brief 构建GROUP BY子句
     * @param sql SQL语句输出流
     */
    void buildGroups(std::ostringstream& sql) const;
    
    /**
     * @brief 构建HAVING子句
     * @param sql SQL语句输出流
     */
    void buildHavings(std::ostringstream& sql) const;
    
    /**
     * @brief 构建ORDER BY子句
     * @param sql SQL语句输出流
     */
    void buildOrders(std::ostringstream& sql) const;

    QueryType _type;
    std::string _table;
    std::vector<std::string> _columns;
    bool _distinct;
    std::vector<JoinClause> _joins;
    std::vector<WhereClause> _wheres;
    std::vector<std::string> _groups;
    std::vector<WhereClause> _havings;
    std::vector<OrderClause> _orders;
    int _limit;
    int _offset;
    std::vector<std::map<std::string, std::string>> _insertData;
    std::map<std::string, std::string> _updateData;
};

} // namespace db
} // namespace CLink